package cn.sfrog.project.biz.applet.service.impl;


import cn.sfrog.project.biz.applet.config.PayUtil;
import cn.sfrog.project.biz.applet.config.WxApiType;
import cn.sfrog.project.biz.applet.config.WxNotifyType;
import cn.sfrog.project.biz.applet.config.WxPayConfig;
import cn.sfrog.project.biz.applet.service.WxPayService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Resource
    private WxPayConfig wxPayConfig;

    @Resource
    private CloseableHttpClient wxPayClient;
    @Resource
    private CloseableHttpClient wxPayNoSignClient; //无需应答签名


    private final ReentrantLock lock = new ReentrantLock();


    /**
     * 创建订单，调用Native支付接口
     * @param openId
     * @return code_url 和 订单号
     * @throws Exception
     */

    @Override
    public Map<String, Object> jsapi(String openId) throws Exception {
        //调用统一下单API
        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType()));

        // 请求body参数
        Gson gson = new Gson();
        Map paramsMap = new HashMap();
        paramsMap.put("appid", wxPayConfig.getAppid());
        paramsMap.put("mchid", wxPayConfig.getMchId());
        paramsMap.put("description", "F17051367944450332");
        paramsMap.put("out_trade_no", "F17051367944450332");
        paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat("/payment/wxCallback"));
//        paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));

        Map amountMap = new HashMap();
        // amountMap.put("total", 1);
        amountMap.put("currency", "CNY");
        paramsMap.put("amount", amountMap);

        Map payerMap = new HashMap();
        payerMap.put("openid",openId);
        paramsMap.put("payer",payerMap);

        //将参数转换成json字符串
        String jsonParams = gson.toJson(paramsMap);
        log.info("请求参数 ===> {}" + jsonParams);

        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        CloseableHttpResponse response = wxPayClient.execute(httpPost);
        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
            int statusCode = response.getStatusLine().getStatusCode();//响应状态码
            if (statusCode == 200) { //处理成功
                log.info("成功, 返回结果 = " + bodyAsString);
                JSONObject jsonObject = JSON.parseObject(bodyAsString);
                Map<String, String> prepay_id = prepayIdCreateSign(jsonObject.get("prepay_id").toString());
                System.out.println(jsonObject.get("prepay_id"));
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("成功");
            } else {
                log.info("小程序下单失败,响应码 = " + statusCode+ ",返回结果 = " + bodyAsString);
                throw new IOException("request failed");
            }
            //响应结果
            Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);

            return null;

        } finally {
            response.close();
        }
    }

    @Override
    public Map<String, Object> App() throws Exception {
//调用统一下单API
        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.APP_PAY.getType()));
        // 请求body参数
        Gson gson = new Gson();
        Map paramsMap = new HashMap();
        paramsMap.put("appid", wxPayConfig.getAppid());
        paramsMap.put("mchid", wxPayConfig.getMchId());
        paramsMap.put("description", "F17051367944450332");
        paramsMap.put("out_trade_no", "F17051367944450332");
        paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));

        Map amountMap = new HashMap();
        // amountMap.put("total", 1);
        amountMap.put("currency", "CNY");
        paramsMap.put("amount", amountMap);
        //将参数转换成json字符串
        String jsonParams = gson.toJson(paramsMap);
        log.info("请求参数 ===> {}" + jsonParams);

        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        CloseableHttpResponse response = wxPayClient.execute(httpPost);
        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
            int statusCode = response.getStatusLine().getStatusCode();//响应状态码
            if (statusCode == 200) { //处理成功
                log.info("成功, 返回结果 = " + bodyAsString);
                JSONObject jsonObject = JSON.parseObject(bodyAsString);
                Map<String, String> prepay_id = prepayIdCreateSign(jsonObject.get("prepay_id").toString());
                System.out.println(jsonObject.get("prepay_id"));
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("成功");
            } else {
                log.info("App下单失败,响应码 = " + statusCode+ ",返回结果 = " + bodyAsString);
                throw new IOException("request failed");
            }
            //响应结果
            Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);

            return null;

        } finally {
            response.close();
        }
    }

    /**
     * 微信支付生成paySign签名调取微信付款页面
     * @param prepay_id
     * @return
     */
    public Map<String, String> prepayIdCreateSign(String prepay_id) {
        Map<String, String> packageParams = new HashMap<String, String>();
        long l = System.currentTimeMillis();
        System.out.println(prepay_id);
        System.out.println("l"+l);
        System.out.println("l"+l/1000);
        PayUtil payUtil = new PayUtil();
        String wxcb4b1cfb36b51c86 = null;
        try {
            wxcb4b1cfb36b51c86 = payUtil.getSign("wxcb4b1cfb36b51c86", l / 1000, String.valueOf(l), "prepay_id=" + prepay_id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(wxcb4b1cfb36b51c86);

        return packageParams;
    }


    /**
     * 对称解密
     * @param bodyMap
     * @return
     */
    private String decryptFromResource(Map<String, Object> bodyMap) throws GeneralSecurityException {

        log.info("密文解密");

        //通知数据
        Map<String, String> resourceMap = (Map) bodyMap.get("resource");
        //数据密文
        String ciphertext = resourceMap.get("ciphertext");
        //随机串
        String nonce = resourceMap.get("nonce");
        //附加数据
        String associatedData = resourceMap.get("associated_data");

        log.info("密文 ===> {}", ciphertext);
        AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
        String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
                nonce.getBytes(StandardCharsets.UTF_8),
                ciphertext);

        log.info("明文 ===> {}", plainText);

        return plainText;
    }



}
